package com.netsdk.demo.customize;

import com.netsdk.demo.util.CaseMenu;
import com.netsdk.lib.NetSDKLib;
import com.netsdk.lib.ToolKits;
import com.netsdk.lib.callback.impl.DefaultDisconnectCallback;
import com.netsdk.lib.callback.impl.DefaultHaveReconnectCallBack;
import com.netsdk.lib.structure.DEV_EVENT_FACERECOGNITION_INFO_V1;
import com.netsdk.lib.structure.DEV_EVENT_VIDEO_NORMAL_DETECTION_INFO;
import com.netsdk.lib.structure.NET_TIME_EX;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import static com.netsdk.lib.Utils.getOsPrefix;

/**
 * @author
 * @version 1.0
 * @description GIP230710010
 * @date 2023/7/17 10:37
 */
public class OemAtmDemo {

	// SDk对象初始化
	public static final NetSDKLib netsdk = NetSDKLib.NETSDK_INSTANCE;
	public static final NetSDKLib configsdk = NetSDKLib.CONFIG_INSTANCE;

	// 判断是否初始化
	private static boolean bInit = false;
	// 判断log是否打开
	private static boolean bLogOpen = false;
	// 设备信息
	private NetSDKLib.NET_DEVICEINFO_Ex deviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
	// 登录句柄
	private static NetSDKLib.LLong m_hLoginHandle = new NetSDKLib.LLong(0);

	// 回调函数需要是静态的，防止被系统回收
	// 断线回调
	private static NetSDKLib.fDisConnect disConnectCB = DefaultDisconnectCallback.getINSTANCE();
	// 重连回调
	private static NetSDKLib.fHaveReConnect haveReConnectCB = DefaultHaveReconnectCallBack.getINSTANCE();

	// 编码格式
	public static String encode;

	static {
		String osPrefix = getOsPrefix();
		if (osPrefix.toLowerCase().startsWith("win32-amd64")) {
			encode = "GBK";
		} else if (osPrefix.toLowerCase().startsWith("linux-amd64")) {
			encode = "UTF-8";
		}
	}

	/**
	 * 获取当前时间
	 */
	public static String GetDate() {
		SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		return simpleDate.format(new java.util.Date()).replaceAll("[^0-9]", "-");
	}

	/**
	 * 初始化SDK库
	 */
	public static boolean Init() {
		bInit = netsdk.CLIENT_Init(disConnectCB, null);// 进程启动时，初始化一次
		if (!bInit) {
			System.out.println("Initialize SDK failed");
			return false;
		}
		// 配置日志
		OemAtmDemo.enableLog();

		// 设置断线重连回调接口, 此操作为可选操作，但建议用户进行设置
		netsdk.CLIENT_SetAutoReconnect(haveReConnectCB, null);

		// 设置登录超时时间和尝试次数，可选
		// 登录请求响应超时时间设置为3S
		int waitTime = 3000;
		// 登录时尝试建立链接 1 次
		int tryTimes = 1;
		netsdk.CLIENT_SetConnectTime(waitTime, tryTimes);
		// 设置更多网络参数， NET_PARAM 的nWaittime ， nConnectTryNum 成员与 CLIENT_SetConnectTime
		// 接口设置的登录设备超时时间和尝试次数意义相同,可选
		NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM();
		// 登录时尝试建立链接的超时时间
		netParam.nConnectTime = 10000;
		// 设置子连接的超时时间
		netParam.nGetConnInfoTime = 3000;
		netsdk.CLIENT_SetNetworkParam(netParam);
		return true;
	}

	/**
	 * 打开 sdk log
	 */
	private static void enableLog() {
		NetSDKLib.LOG_SET_PRINT_INFO setLog = new NetSDKLib.LOG_SET_PRINT_INFO();
		File path = new File("sdklog/");
		if (!path.exists())
			path.mkdir();

		// 这里的log保存地址依据实际情况自己调整
		String logPath = path.getAbsoluteFile().getParent() + "\\sdklog\\" + "sdklog" + GetDate() + ".log";
		setLog.nPrintStrategy = 0;
		setLog.bSetFilePath = 1;
		System.arraycopy(logPath.getBytes(), 0, setLog.szLogFilePath, 0, logPath.getBytes().length);
		System.out.println(logPath);
		setLog.bSetPrintStrategy = 1;
		bLogOpen = netsdk.CLIENT_LogOpen(setLog);
		if (!bLogOpen)
			System.err.println("Failed to open NetSDK log");
	}

	/**
	 * 高安全登录
	 */
	public void loginWithHighLevel() {
		// 输入结构体参数
		NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY pstlnParam = new NetSDKLib.NET_IN_LOGIN_WITH_HIGHLEVEL_SECURITY() {
			{
				szIP = m_strIpAddr.getBytes();
				nPort = m_nPort;
				szUserName = m_strUser.getBytes();
				szPassword = m_strPassword.getBytes();
			}
		};
		// 输出结构体参数
		NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam = new NetSDKLib.NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY();

		// 写入sdk
		m_hLoginHandle = netsdk.CLIENT_LoginWithHighLevelSecurity(pstlnParam, pstOutParam);
		if (m_hLoginHandle.longValue() == 0) {
			System.err.printf("Login Device[%s] Port[%d]Failed. %s\n", m_strIpAddr, m_nPort,
					netsdk.CLIENT_GetLastError());
		} else {
			deviceInfo = pstOutParam.stuDeviceInfo; // 获取设备信息
			System.out.println("Login Success");
			System.out.println("Device Address：" + m_strIpAddr);
			System.out.println("设备包含：" + deviceInfo.byChanNum + "个通道");
		}
	}

	/**
	 * 退出
	 */
	public void logOut() {
		if (m_hLoginHandle.longValue() != 0) {
			netsdk.CLIENT_Logout(m_hLoginHandle);
			System.out.println("LogOut Success");
		}
	}

	/**
	 * 清理sdk环境并退出
	 */
	public static void cleanAndExit() {
		if (bLogOpen) {
			netsdk.CLIENT_LogClose(); // 关闭sdk日志打印
		}
		netsdk.CLIENT_Cleanup(); // 进程关闭时，调用一次
		System.exit(0);
	}

	public static Pointer GetStringToPointer(String src, String charset) {
		Pointer pointer = null;
		try {
			byte[] b = src.getBytes(charset);

			pointer = new Memory(b.length + 1);
			pointer.clear(b.length + 1);

			pointer.write(0, b, 0, b.length);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return pointer;
	}

	int channel = -1;
	NetSDKLib.LLong attachHandle = new NetSDKLib.LLong(0);

	/**
	 * 订阅智能任务
	 */

	public NetSDKLib.LLong AttachEventRealLoadPic() {
		// 先退订，设备不会对重复订阅作校验，重复订阅后会有重复的事件返回
		if (attachHandle.longValue() != 0) {
			this.DetachEventRealLoadPic();
		}

		// 需要图片
		int bNeedPicture = 1;
		attachHandle = netsdk.CLIENT_RealLoadPictureEx(m_hLoginHandle, channel, NetSDKLib.EVENT_IVS_ALL, bNeedPicture,
				AnalyzerDataCB.getInstance(), null, null);
		if (attachHandle.longValue() != 0) {
			System.out.printf("Chn[%d] CLIENT_RealLoadPictureEx Success\n", channel);
		} else {
			System.out.printf("Chn[%d] CLIENT_RealLoadPictureEx Failed!LastError = %s\n", channel,
					ToolKits.getErrorCode());
		}

		return attachHandle;
	}

	/**
	 * 报警事件（智能）回调
	 */
	private static class AnalyzerDataCB implements NetSDKLib.fAnalyzerDataCallBack {
		private final File picturePath;
		private static AnalyzerDataCB instance;

		private AnalyzerDataCB() {
			picturePath = new File("./AnalyzerPicture/");
			if (!picturePath.exists()) {
				picturePath.mkdirs();
			}
		}

		public static AnalyzerDataCB getInstance() {
			if (instance == null) {
				synchronized (AnalyzerDataCB.class) {
					if (instance == null) {
						instance = new AnalyzerDataCB();
					}
				}
			}
			return instance;
		}

		@Override
		public int invoke(NetSDKLib.LLong lAnalyzerHandle, int dwAlarmType, Pointer pAlarmInfo, Pointer pBuffer,
				int dwBufSize, Pointer dwUser, int nSequence, Pointer reserved) {
			if (lAnalyzerHandle == null || lAnalyzerHandle.longValue() == 0) {
				return -1;
			}

			switch (dwAlarmType) {
			case NetSDKLib.EVENT_IVS_FACERECOGNITION: {
				System.out.println("目标识别事件");

				DEV_EVENT_FACERECOGNITION_INFO_V1 msg = new DEV_EVENT_FACERECOGNITION_INFO_V1();
				ToolKits.GetPointerData(pAlarmInfo, msg);
				System.out.println("nCandidateNum:" + msg.nCandidateNum);
				if (msg.nCandidateNum > 0) {
					NetSDKLib.CANDIDATE_INFOEX[] stuCandidates = (NetSDKLib.CANDIDATE_INFOEX[]) new NetSDKLib.CANDIDATE_INFOEX()
							.toArray(msg.nCandidateNum);
					for (int i = 0; i < stuCandidates.length; i++) {
						stuCandidates[i] = new NetSDKLib.CANDIDATE_INFOEX();
					}
					ToolKits.GetPointerDataToStructArr(msg.stuCandidates, stuCandidates);
					try {
						System.out.println(
								"szPersonName:" + new String(stuCandidates[0].stPersonInfo.szPersonName, "GBK"));
						System.out.println("szGroupID:" + new String(stuCandidates[0].stPersonInfo.szGroupID, "GBK"));
						System.out
								.println("szGroupName:" + new String(stuCandidates[0].stPersonInfo.szGroupName, "GBK"));
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}
				}
				System.out.println("nChannelID:" + msg.nChannelID);
				System.out.println("目标识别事件 时间(UTC):" + msg.UTC);

				/////////////// 保存全景图 ///////////////////
				if (msg.bGlobalScenePic == 1 && msg.stuGlobalScenePicInfo != null) {
					String bigPicture = picturePath + "\\" + "Global" + System.currentTimeMillis() + ".jpg";
					ToolKits.savePicture(pBuffer, msg.stuGlobalScenePicInfo.dwOffSet,
							msg.stuGlobalScenePicInfo.dwFileLenth, bigPicture);

				}
				/////////////// 保存人脸图 /////////////////////////
				if (msg.stuObject.stPicInfo != null) {
					String strPersonPicPathName = picturePath + "\\" + "Person" + System.currentTimeMillis() + ".jpg";
					ToolKits.savePicture(pBuffer, msg.stuObject.stPicInfo.dwOffSet, msg.stuObject.stPicInfo.dwFileLenth,
							strPersonPicPathName);
				}

				break;

			}
			case NetSDKLib.EVENT_IVS_VIDEO_NORMAL_DETECTION: { // 视频正常事件,在视频诊断检测周期结束时,将未报错的诊断项上报正常事件
				System.out.println("视频正常事件,在视频诊断检测周期结束时,将未报错的诊断项上报正常事件");
				DEV_EVENT_VIDEO_NORMAL_DETECTION_INFO info = new DEV_EVENT_VIDEO_NORMAL_DETECTION_INFO();
				ToolKits.GetPointerData(pAlarmInfo, info);
				int nChannelID = info.nChannelID;
				System.out.println("nChannelID:" + nChannelID);

				int nAction = info.nAction;
				System.out.println("nAction:" + nAction);

				int nEventID = info.nEventID;
				System.out.println("nEventID:" + nEventID);

				NET_TIME_EX utc = info.UTC;
				System.out.printf("utc:" + utc);

				double dbPTS = info.dbPTS;
				System.out.printf("dbPTS:" + dbPTS);

				int emDetectType = info.emDetectType;
				System.out.printf("emDetectType:" + emDetectType);

				break;
			}
			default:
				System.out.println("其他事件--------------------" + dwAlarmType);
				break;
			}
			return 0;
		}
	}

	/**
	 * 停止侦听智能事件
	 */
	public void DetachEventRealLoadPic() {
		if (this.attachHandle.longValue() != 0) {
			netsdk.CLIENT_StopLoadPic(this.attachHandle);
		}
	}

	/**
	 * 添加人脸库
	 */
	public boolean addFaceRecognitionGroup() {

		String groupName = "123";

		NetSDKLib.NET_ADD_FACERECONGNITION_GROUP_INFO addGroupInfo = new NetSDKLib.NET_ADD_FACERECONGNITION_GROUP_INFO();
		try {
			System.arraycopy(groupName.getBytes(encode), 0, addGroupInfo.stuGroupInfo.szGroupName, 0,
					groupName.getBytes(encode).length);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		// 入参
		NetSDKLib.NET_IN_OPERATE_FACERECONGNITION_GROUP stIn = new NetSDKLib.NET_IN_OPERATE_FACERECONGNITION_GROUP();
		stIn.emOperateType = NetSDKLib.EM_OPERATE_FACERECONGNITION_GROUP_TYPE.NET_FACERECONGNITION_GROUP_ADD; // 添加人员组信息
		stIn.pOPerateInfo = addGroupInfo.getPointer();

		// 出参
		NetSDKLib.NET_OUT_OPERATE_FACERECONGNITION_GROUP stOut = new NetSDKLib.NET_OUT_OPERATE_FACERECONGNITION_GROUP();

		addGroupInfo.write();
		boolean bRet = netsdk.CLIENT_OperateFaceRecognitionGroup(m_hLoginHandle, stIn, stOut, 4000);
		addGroupInfo.read();

		if (bRet) {
			System.out.println("人员组ID : " + new String(stOut.szGroupId).trim()); // 新增记录的人员组ID,唯一标识一组人员
			System.out.println("添加人脸库成功");
		} else {
			System.out.println("添加人脸库失败：" + ToolKits.getErrorCode());
			return false;
		}

		return true;
	}

	/**
	 * 修改人脸库
	 */
	public boolean modifyFaceRecognitionGroup() {
		String groupName = "123";
		String groupId = "1";

		NetSDKLib.NET_MODIFY_FACERECONGNITION_GROUP_INFO modifyGroupInfo = new NetSDKLib.NET_MODIFY_FACERECONGNITION_GROUP_INFO();
		try {
			System.arraycopy(groupName.getBytes(encode), 0, modifyGroupInfo.stuGroupInfo.szGroupName, 0,
					groupName.getBytes(encode).length);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.arraycopy(groupId.getBytes(), 0, modifyGroupInfo.stuGroupInfo.szGroupId, 0, groupId.getBytes().length); // 给人员组ID赋值，要用数组拷贝

		// 入参
		NetSDKLib.NET_IN_OPERATE_FACERECONGNITION_GROUP stIn = new NetSDKLib.NET_IN_OPERATE_FACERECONGNITION_GROUP();
		stIn.emOperateType = NetSDKLib.EM_OPERATE_FACERECONGNITION_GROUP_TYPE.NET_FACERECONGNITION_GROUP_MODIFY; // 修改人员组信息
		stIn.pOPerateInfo = modifyGroupInfo.getPointer();

		// 出参
		NetSDKLib.NET_OUT_OPERATE_FACERECONGNITION_GROUP stOut = new NetSDKLib.NET_OUT_OPERATE_FACERECONGNITION_GROUP();

		modifyGroupInfo.write();
		boolean bRet = netsdk.CLIENT_OperateFaceRecognitionGroup(m_hLoginHandle, stIn, stOut, 4000);
		modifyGroupInfo.read();

		if (bRet) {
			System.out.println("修改人脸库成功");
		} else {
			System.out.println("修改人脸库失败：" + ToolKits.getErrorCode());
			return false;
		}

		return true;
	}

	/**
	 * 删除人脸库
	 */
	public boolean deleteFaceRecognitionGroup() {
		String groupId = "1";
		NetSDKLib.NET_DELETE_FACERECONGNITION_GROUP_INFO deleteGroupInfo = new NetSDKLib.NET_DELETE_FACERECONGNITION_GROUP_INFO();
		System.arraycopy(groupId.getBytes(), 0, deleteGroupInfo.szGroupId, 0, groupId.getBytes().length); // 给人员组ID赋值，要用数组拷贝

		// 入参
		NetSDKLib.NET_IN_OPERATE_FACERECONGNITION_GROUP stIn = new NetSDKLib.NET_IN_OPERATE_FACERECONGNITION_GROUP();
		stIn.emOperateType = NetSDKLib.EM_OPERATE_FACERECONGNITION_GROUP_TYPE.NET_FACERECONGNITION_GROUP_DELETE; // 删除人员组信息
		stIn.pOPerateInfo = deleteGroupInfo.getPointer();

		// 出参
		NetSDKLib.NET_OUT_OPERATE_FACERECONGNITION_GROUP stOut = new NetSDKLib.NET_OUT_OPERATE_FACERECONGNITION_GROUP();

		deleteGroupInfo.write();
		boolean bRet = netsdk.CLIENT_OperateFaceRecognitionGroup(m_hLoginHandle, stIn, stOut, 4000);
		deleteGroupInfo.read();

		if (bRet) {
			System.out.println("删除人脸库成功!");
		} else {
			System.out.println("删除人脸库失败：" + ToolKits.getErrorCode());
			return false;
		}

		return true;
	}

	/**
	 * 查询人脸库人员组信息
	 * 
	 */
	public boolean findGroupInfo() {
		// groupId 需要查找的人脸库ID; 为空表示查找所有的人脸库
		String groupId = "1";
		// 入参
		NetSDKLib.NET_IN_FIND_GROUP_INFO stIn = new NetSDKLib.NET_IN_FIND_GROUP_INFO();
		System.arraycopy(groupId.getBytes(), 0, stIn.szGroupId, 0, groupId.getBytes().length);

		// 出参
		int max = 20;
		NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[] groupInfo = new NetSDKLib.NET_FACERECONGNITION_GROUP_INFO[max];
		for (int i = 0; i < max; i++) {
			groupInfo[i] = new NetSDKLib.NET_FACERECONGNITION_GROUP_INFO();
		}

		NetSDKLib.NET_OUT_FIND_GROUP_INFO stOut = new NetSDKLib.NET_OUT_FIND_GROUP_INFO();
		stOut.pGroupInfos = new Memory(groupInfo[0].size() * 20); // Pointer初始化
		stOut.pGroupInfos.clear(groupInfo[0].size() * 20);
		stOut.nMaxGroupNum = max;

		ToolKits.SetStructArrToPointerData(groupInfo, stOut.pGroupInfos); // 将数组内存拷贝给Pointer

		if (netsdk.CLIENT_FindGroupInfo(m_hLoginHandle, stIn, stOut, 4000)) {
			ToolKits.GetPointerDataToStructArr(stOut.pGroupInfos, groupInfo); // 将Pointer的值输出到 数组
																				// NET_FACERECONGNITION_GROUP_INFO
			for (int i = 0; i < stOut.nRetGroupNum; i++) {

				// 人脸库名称
				try {
					System.out.println("[" + i + "]" + new String(groupInfo[i].szGroupName, encode).trim());
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}

				// 人脸库ID
				System.out.println("[" + i + "]" + new String(groupInfo[i].szGroupId).trim());

				// 相似度
				String nSimilarityCount = "";
				for (int j = 0; j < groupInfo[i].nRetSimilarityCount; j++) {
					nSimilarityCount = nSimilarityCount + "  " + String.valueOf(groupInfo[i].nSimilarity[j]);
				}
				System.out.println("[" + i + "]" + nSimilarityCount);

				String nChannelCount = "";
				for (int j = 0; j < groupInfo[i].nRetChnCount; j++) {
					nChannelCount = nChannelCount + "  " + String.valueOf(groupInfo[i].nChannel[j]);
				}
				System.out.println("[" + i + "]" + nChannelCount);
			}
		} else {
			System.err.println("查询人员信息失败" + ToolKits.getErrorCode());
			return false;
		}

		return true;
	}

	/**
	 * 目标识别数据库查询
	 */
	public void findFile() {
		int type = NetSDKLib.EM_FILE_QUERY_TYPE.NET_FILE_QUERY_FACE;

		/**
		 * 查询条件
		 */
		NetSDKLib.MEDIAFILE_FACERECOGNITION_PARAM findContion = new NetSDKLib.MEDIAFILE_FACERECOGNITION_PARAM();

		// 开始时间
		findContion.stStartTime.dwYear = 2018;
		findContion.stStartTime.dwMonth = 6;
		findContion.stStartTime.dwDay = 1;
		findContion.stStartTime.dwHour = 13;
		findContion.stStartTime.dwMinute = 0;
		findContion.stStartTime.dwSecond = 0;

		// 结束时间
		findContion.stEndTime.dwYear = 2018;
		findContion.stEndTime.dwMonth = 6;
		findContion.stEndTime.dwDay = 1;
		findContion.stEndTime.dwHour = 14;
		findContion.stEndTime.dwMinute = 59;
		findContion.stEndTime.dwSecond = 59;

		/**
		 * 以下注释的查询条件参数，目前设备不支持，后续会逐渐增加
		 */
//		// 地点,支持模糊匹配
//		String machineAddress = "";
//		System.arraycopy(machineAddress.getBytes(), 0, findContion.szMachineAddress, 0, machineAddress.getBytes().length);
//
//		// 待查询报警类型
//		findContion.nAlarmType = EM_FACERECOGNITION_ALARM_TYPE.NET_FACERECOGNITION_ALARM_TYPE_ALL;

		// 通道号
		findContion.nChannelId = 0;

//		// 人员组数
//		findContion.nGroupIdNum = 1;
//
//		// 人员组ID(人脸库ID)
//		String groupId = "";
//		System.arraycopy(groupId.getBytes(), 0, findContion.szGroupIdArr[0].szGroupId, 0, groupId.getBytes().length);
//
//		// 人员信息扩展是否有效
//		findContion.abPersonInfoEx = 1;
//
//		// 人员组ID(人脸库ID)
//		System.arraycopy(groupId.getBytes(), 0, findContion.stPersonInfoEx.szGroupID, 0, groupId.getBytes().length);

		findContion.write();
		NetSDKLib.LLong lFindHandle = netsdk.CLIENT_FindFileEx(m_hLoginHandle, type, findContion.getPointer(), null,
				3000);
		if (lFindHandle.longValue() == 0) {
			System.err.println("FindFileEx Failed!" + ToolKits.getErrorCode());
			return;
		}
		findContion.read();

		int nMaxConut = 10;
		NetSDKLib.MEDIAFILE_FACERECOGNITION_INFO[] faceRecognitionInfo = new NetSDKLib.MEDIAFILE_FACERECOGNITION_INFO[nMaxConut];
		for (int i = 0; i < faceRecognitionInfo.length; ++i) {
			faceRecognitionInfo[i] = new NetSDKLib.MEDIAFILE_FACERECOGNITION_INFO();
			faceRecognitionInfo[i].bUseCandidatesEx = 1;
		}

		int MemorySize = faceRecognitionInfo[0].size() * nMaxConut;
		Pointer pointer = new Memory(MemorySize);
		pointer.clear(MemorySize);

		ToolKits.SetStructArrToPointerData(faceRecognitionInfo, pointer);

		// 循环查询
		int nCurCount = 0;
		int nFindCount = 0;
		while (true) {
			int nRetCount = netsdk.CLIENT_FindNextFileEx(lFindHandle, nMaxConut, pointer, MemorySize, null, 3000);
			ToolKits.GetPointerDataToStructArr(pointer, faceRecognitionInfo);

			if (nRetCount <= 0) {
				System.err.println("FindNextFileEx failed!" + netsdk.CLIENT_GetLastError());
				break;
			}

			for (int i = 0; i < nRetCount; i++) {
				nFindCount = i + nCurCount * nMaxConut;
				System.out.println("[" + nFindCount + "]通道号 :" + faceRecognitionInfo[i].nChannelId);
				System.out.println("[" + nFindCount + "]报警发生时间 :" + faceRecognitionInfo[i].stTime.toStringTime());

				// 人脸图
				System.out.println("[" + nFindCount + "]人脸图路径 :"
						+ new String(faceRecognitionInfo[i].stObjectPic.szFilePath).trim());

				// 对比图
				System.out.println("[" + nFindCount + "]匹配到的候选对象数量 :" + faceRecognitionInfo[i].nCandidateNum);
				for (int j = 0; j < faceRecognitionInfo[i].nCandidateNum; j++) {
					for (int k = 0; k < faceRecognitionInfo[i].stuCandidatesPic[j].nFileCount; k++) {
						System.out.println("[" + nFindCount + "]对比图路径 :"
								+ new String(faceRecognitionInfo[i].stuCandidatesPic[j].stFiles[k].szFilePath).trim());
					}
				}

				// 对比信息
				System.out.println("[" + nFindCount + "]匹配到的候选对象数量 :" + faceRecognitionInfo[i].nCandidateExNum);
				for (int j = 0; j < faceRecognitionInfo[i].nCandidateExNum; j++) {
					System.out.println("[" + nFindCount + "]人员唯一标识符 :"
							+ new String(faceRecognitionInfo[i].stuCandidatesEx[j].stPersonInfo.szUID).trim());

					// 以下参数，设备有些功能没有解析，如果想要知道 对比图的人员信息，可以根据上面获取的 szUID，用 findFaceRecognitionDB()
					// 来查询人员信息。
					// findFaceRecognitionDB() 此示例的方法是根据 GroupId来查询的，这里的查询，GroupId不填，根据 szUID 来查询
					System.out.println("[" + nFindCount + "]姓名 :"
							+ new String(faceRecognitionInfo[i].stuCandidatesEx[j].stPersonInfo.szPersonName).trim());
					System.out.println(
							"[" + nFindCount + "]相似度 :" + faceRecognitionInfo[i].stuCandidatesEx[j].bySimilarity);
					System.out.println(
							"[" + nFindCount + "]年龄 :" + faceRecognitionInfo[i].stuCandidatesEx[j].stPersonInfo.byAge);
					System.out.println("[" + nFindCount + "]人脸库名称 :"
							+ new String(faceRecognitionInfo[i].stuCandidatesEx[j].stPersonInfo.szGroupName).trim());
					System.out.println("[" + nFindCount + "]人脸库ID :"
							+ new String(faceRecognitionInfo[i].stuCandidatesEx[j].stPersonInfo.szGroupID).trim());
				}

				System.out.println();
			}

			if (nRetCount < nMaxConut) {
				break;
			} else {
				nCurCount++;
			}
		}

		netsdk.CLIENT_FindCloseEx(lFindHandle);
	}

	public void RunTest() {
		System.out.println("Run Test");
		CaseMenu menu = new CaseMenu();
		menu.addItem(new CaseMenu.Item(this, "订阅报警事件任务", "AttachEventRealLoadPic"));
		menu.addItem(new CaseMenu.Item(this, "退订报警事件任务", "DetachEventRealLoadPic"));
		menu.addItem(new CaseMenu.Item(this, "添加人脸库", "addFaceRecognitionGroup"));
		menu.addItem(new CaseMenu.Item(this, "修改人脸库", "modifyFaceRecognitionGroup"));
		menu.addItem(new CaseMenu.Item(this, "删除人脸库", "deleteFaceRecognitionGroup"));
		menu.addItem(new CaseMenu.Item(this, "目标识别数据库查询", "findGroupInfo"));
		menu.run();
	}

	// 配置登陆地址，端口，用户名，密码
	private String m_strIpAddr = "172.12.5.158";
	private int m_nPort = 37777;
	private String m_strUser = "admin";
	private String m_strPassword = "admin123";

	public static void main(String[] args) {
		OemAtmDemo demo = new OemAtmDemo();
		demo.InitTest();
		demo.RunTest();
		demo.EndTest();

	}

	/**
	 * 初始化测试
	 */
	public void InitTest() {
		OemAtmDemo.Init();

		this.loginWithHighLevel();
	}

	/**
	 * 结束测试
	 */
	public void EndTest() {
		System.out.println("End Test");
		this.logOut(); // 登出设备
		System.out.println("See You...");
		OemAtmDemo.cleanAndExit(); // 清理资源并退出
	}

}
